!------------------------------------------------------------------------------
! TJU/Department of Mechanics, Fluid Mechanics, Code START
!------------------------------------------------------------------------------
!> @Author: Jianxin Liu shookware@tju.edu.cn
!> @Date: 2024-08-06 14:32:04
!> @LastEditTime: 2024-08-13 14:23:02
!> @LastEditors: Jianxin Liu shookware@tju.edu.cn
!> @Description:
!> @FilePath: /START_NS_3D/src/finite_difference_scheme/module_finite_difference_scheme.f90
!> @Copyright (c) 2024 by Jianxin Liu email: shookware@tju.edu.cn, All Rights Reserved.
!------------------------------------------------------------------------------
module module_finite_difference_scheme

   use petsc_wrapper_matrix, only: type_self_matrix
   use petsc_wrapper_vector
   implicit none
   private
   type, abstract, public :: type_fdm_scheme_base

      integer :: length = -1
      integer :: stencil_width = -1
      logical :: flg_bounds(2) = .FALSE.

   contains

      procedure(interface_create), deferred :: create
      procedure(interface_diff), deferred :: diff
      procedure(interface_Destroy), deferred :: destroy

      procedure :: set_parameters => SetParametersFDMScheme

   end type type_fdm_scheme_base

   abstract interface
      subroutine interface_create(this, length, stencil_width, flg_bounds)
         import
         class(type_fdm_scheme_base), intent(inout) :: this
         integer, intent(in) :: length
         integer, intent(in) :: stencil_width
         logical, intent(in) :: flg_bounds(2)

      end subroutine interface_create

      subroutine interface_destroy(this)
         import
         class(type_fdm_scheme_base), intent(inout) :: this
      end subroutine interface_destroy

      subroutine interface_diff(this, f, df)
         import
         class(type_fdm_scheme_base), intent(inout) :: this
         class(type_vector_base), intent(in) :: f
         class(type_vector_base), intent(inout) :: df
      end subroutine
   end interface

   type, extends(type_fdm_scheme_base), public :: type_fdm_scheme_1back
      type(type_self_matrix) :: D

   contains
      procedure :: create => CreateFDMScheme_1Back
      procedure :: diff => DiffFDMScheme_1Back
      procedure :: destroy => DestroyFDMScheme_1Back

   end type type_fdm_scheme_1back

   interface
      module subroutine CreateFDMScheme_1Back(this, length, stencil_width, flg_bounds)
         implicit none
         class(type_fdm_scheme_1back), intent(inout) :: this
         integer, intent(in) :: length
         integer, intent(in) :: stencil_width
         logical, intent(in) :: flg_bounds(2)
      end subroutine CreateFDMScheme_1Back
      module subroutine DiffFDMScheme_1Back(this, f, df)
         implicit none
         class(type_fdm_scheme_1back), intent(inout) :: this
         class(type_vector_base), intent(in) :: f
         class(type_vector_base), intent(inout) :: df
      end subroutine DiffFDMScheme_1Back
      module subroutine DestroyFDMScheme_1Back(this)
         implicit none
         class(type_fdm_scheme_1back), intent(inout) :: this
      end subroutine DestroyFDMScheme_1Back
   end interface

   type, extends(type_fdm_scheme_base), public :: type_fdm_scheme_4center
      type(type_self_matrix) :: D
   contains

      procedure :: create => CreateFDMScheme_4Center
      procedure :: diff => DiffFDMScheme_4Center
      procedure :: destroy => DestroyFDMScheme_4Center

   end type type_fdm_scheme_4center

   interface
      module subroutine CreateFDMScheme_4Center(this, length, stencil_width, flg_bounds)
         implicit none
         class(type_fdm_scheme_4center), intent(inout) :: this
         integer, intent(in) :: length
         integer, intent(in) :: stencil_width
         logical, intent(in) :: flg_bounds(2)
      end subroutine CreateFDMScheme_4Center
      module subroutine DiffFDMScheme_4Center(this, f, df)
         implicit none
         class(type_fdm_scheme_4center), intent(inout) :: this
         class(type_vector_base), intent(in) :: f
         class(type_vector_base), intent(inout) :: df
      end subroutine DiffFDMScheme_4Center
      module subroutine DestroyFDMScheme_4Center(this)
         implicit none
         class(type_fdm_scheme_4center), intent(inout) :: this
      end subroutine DestroyFDMScheme_4center
   end interface

contains

   subroutine SetParametersFDMScheme(this, length, stencil_width, flg_bounds)
      implicit none
      class(type_fdm_scheme_base), intent(inout) :: this
      integer, intent(in) :: length, stencil_width
      logical, intent(in) :: flg_bounds(2)

      this%length = length
      this%stencil_width = stencil_width
      this%flg_bounds = flg_bounds

   end subroutine SetParametersFDMScheme

end module module_finite_difference_scheme
